package org.chen.consumer;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.chen.domain.dto.MessageData;
import org.chen.client.HeyGenClient;
import org.chen.common.constant.ArticleStatusEnum;
import org.chen.common.constant.VideoStatusEnum;
import org.chen.common.exception.ServiceException;
import org.chen.config.HeyGenProperties;
import org.chen.domain.entity.ApiKeyEntity;
import org.chen.domain.entity.TaskBackground;
import org.chen.domain.entity.UserVideoConfig;
import org.chen.domain.entity.VideoTask;
import org.chen.mapper.*;
import org.chen.request.VideoGenerateRequest;
import org.chen.response.VideoGenerateResponse;
import org.chen.utils.VideoRedisUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Collections;

@Component
@Slf4j
@RequiredArgsConstructor
public class VideoTaskConsumer {
    
    private final HeyGenClient heyGenClient;
    private final VideoTaskMapper taskMapper;
    private final ArticleMapper articleMapper;
    private final VideoRedisUtils videoRedisUtils;
    private final UserVideoConfigMapper configMapper;
    private final ApiKeyMapper apiKeyMapper;
    private final HeyGenProperties heyGenProperties;
    private final TaskBackgroundMapper taskBackgroundMapper;

    @RabbitListener(
        queues = "video.task.queue",
        containerFactory = "videoTaskListenerFactory"
    )
    public void handleVideoTask(MessageData messageData, Message message, Channel channel) {
        VideoTask task = messageData.getVideoTask();
        String taskId = task.getId();

        log.info("Received video task: {}", taskId);

        try {
            Integer retryCount = taskMapper.getRetryCount(taskId);
            if (retryCount == null) {
                retryCount = 0;
                // 初始化重试计数
                taskMapper.initRetryCount(taskId, retryCount);
            }

            log.info("Processing task: {}, current retry count: {}", taskId, retryCount);

            processVideoTask(messageData);

            // 处理成功，重置重试计数
            taskMapper.resetRetryCount(taskId);

            // 手动确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            log.info("Successfully processed video task: {}", taskId);
            
        } catch (Exception e) {
            log.error("Failed to process video task: {}", taskId, e);

            try {
                // 查询最新的重试计数
                Integer retryCount = taskMapper.getRetryCount(taskId);
                if (retryCount == null) {
                    retryCount = 0;
                    taskMapper.initRetryCount(taskId, retryCount);
                }

                if (retryCount < getMaxRetryCount()) {
                    // 增加重试计数
                    taskMapper.incrementRetryCount(taskId);

                    // 拒绝消息并重新入队
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
                    log.info("Message requeued for retry. Task: {}, Retry count: {}", taskId, retryCount + 1);
                } else {
                    // 超过最大重试次数，拒绝消息并不重新入队
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);

                    // 更新任务状态为失败
                    handleGenerationError(task, e);
                    log.warn("Max retry count reached. Task: {}", taskId);
                }
            } catch (IOException ex) {
                log.error("Error handling message rejection for task: {}", taskId, ex);
            }
        }
    }

    private void processVideoTask(MessageData messageData) {
        VideoTask task = messageData.getVideoTask();
        try {
            // 1. 获取或创建用户视频配置
            UserVideoConfig userVideoConfig = getUserVideoConfig(messageData);

            // 2. 构建请求
            VideoGenerateRequest request = buildRequest(messageData.getVideoTask(), userVideoConfig);

            // 3. 调用API生成视频
            VideoGenerateResponse response = heyGenClient.generateVideo(request);

            // 4. 处理响应
            if (response != null && response.getData() != null && response.getData().getVideo_id() != null) {
                handleSuccessResponse(messageData.getVideoTask(), response);

                // 如果是多数字人模式的任务，记录到任务组
                if (Boolean.TRUE.equals(task.getIsMultiAvatar()) && task.getTaskGroupId() != null) {
                    videoRedisUtils.addTaskToGroup(task.getTaskGroupId(), task.getId());
                }
            } else {
                throw new ServiceException("API响应数据为空或缺少视频ID，任务ID: " + messageData.getVideoTask().getId());
            }

        } catch (Exception e) {
            handleGenerationError(messageData.getVideoTask(), e);
            log.error("视频生成失败，任务ID: {}, 错误信息: {}", messageData.getVideoTask().getId(), e.getMessage(), e);
            throw new ServiceException("视频生成过程中发生错误: " + e.getMessage(), e);
        }
    }

    /**
     * 获取或创建用户视频配置
     */
    private UserVideoConfig getUserVideoConfig(MessageData messageData) {
        VideoTask videoTask = messageData.getVideoTask();

        // 如果没有配置ID，使用用户提供的配置或根据背景创建新配置
        if (videoTask.getConfigId() == null || videoTask.getConfigId().isEmpty()) {
            if (messageData.getUserVideoConfig() != null) {
                return messageData.getUserVideoConfig();
            } else {
                return createConfigFromBackground(videoTask);
            }
        }
        // 如果有配置ID，则从数据库获取配置并可能更新宽高
        else {
            UserVideoConfig config = configMapper.selectById(videoTask.getConfigId());
            if (config == null) {
                throw new ServiceException("找不到指定的视频配置，配置ID: " + videoTask.getConfigId());
            }

            // 如果用户提供了新的宽高，则更新配置
            if (messageData.getUserVideoConfig() != null &&
                    messageData.getUserVideoConfig().getWidth() != null &&
                    messageData.getUserVideoConfig().getHeight() != null) {
                config.setWidth(messageData.getUserVideoConfig().getWidth());
                config.setHeight(messageData.getUserVideoConfig().getHeight());
            }

            return config;
        }
    }

    /**
     * 根据背景ID创建新的用户视频配置
     */
    private UserVideoConfig createConfigFromBackground(VideoTask videoTask) {
        TaskBackground taskBackground = taskBackgroundMapper.selectById(videoTask.getBackgroundId());
        if (taskBackground == null) {
            throw new ServiceException("找不到指定的背景，背景ID: " + videoTask.getBackgroundId());
        }

        UserVideoConfig userVideoConfig = new UserVideoConfig();
        userVideoConfig.setWidth(videoTask.getWidth());
        userVideoConfig.setHeight(videoTask.getHeight());
        userVideoConfig.setIsCaption(false);
        userVideoConfig.setBackgroundType(taskBackground.getBackgroundType());

        // 根据背景类型设置属性
        if ("image".equals(taskBackground.getBackgroundType()) ||
                "video".equals(taskBackground.getBackgroundType())) {

            // 设置背景URL或ID
            if (taskBackground.getBackgroundId() == null || taskBackground.getBackgroundId().isEmpty()) {
                userVideoConfig.setBackgroundUrl(taskBackground.getBackgroundUrl());
            } else {
                userVideoConfig.setBackgroundId(taskBackground.getBackgroundId());
            }

            userVideoConfig.setBackgroundFit(taskBackground.getBackgroundFit());

            // 视频类型特有属性
            if ("video".equals(taskBackground.getBackgroundType())) {
                userVideoConfig.setBackgroundPlayStyle(taskBackground.getBackgroundPlayStyle());
            }
        } else {
            // 纯色背景
            userVideoConfig.setBackgroundColor(taskBackground.getBackgroundColor());
        }

        return userVideoConfig;
    }

    private void handleSuccessResponse(VideoTask task, VideoGenerateResponse response) {
        String videoId = response.getData().getVideo_id();
        task.setVideoId(videoId);
        
        if (response.getData().getApi_key() != null) {
            task.setApiKey(response.getData().getApi_key());
            task.setStatus(VideoStatusEnum.GENERATING.getCode());
        } else {
//            videoRedisUtils.saveVideoId(videoId);
        }
        videoRedisUtils.saveVideoId(videoId);

        int updated = taskMapper.updateById(task);
        if (updated == 0) {
            throw new ServiceException("更新任务状态失败");
        }

        log.info("Successfully updated task with video_id: {}, task_id: {}",
                response.getData().getVideo_id(), task.getId());
    }
    
    private void handleGenerationError(VideoTask task, Exception e) {
        task.setStatus(VideoStatusEnum.FAILED.getCode());
        task.setErrorMessage(e.getMessage());
        taskMapper.updateById(task);
        
        articleMapper.updateStatus(task.getArticleId(), ArticleStatusEnum.FAILED.getCode());
    }
    
    private int getMaxRetryCount() {
        return 3; // 可以从配置中读取
    }

    private VideoGenerateRequest buildRequest(VideoTask task, UserVideoConfig userVideoConfig) {
        String callbackUrl;
        ApiKeyEntity apiKey = apiKeyMapper.selectOne(new QueryWrapper<ApiKeyEntity>().eq("api_key", task.getApiKey()));
        if (apiKey == null) {
            callbackUrl = heyGenProperties.getCallbackUrl();
        }else {
            callbackUrl = apiKey.getCallbackUrl();
        }

        // 构建背景属性
        VideoGenerateRequest.Background background = buildBackground(userVideoConfig);

        // 使用用户配置的偏移量和缩放值
        double xOffset = userVideoConfig.getXOffset() != null ? userVideoConfig.getXOffset() : 0.0;
        double yOffset = userVideoConfig.getYOffset() != null ? userVideoConfig.getYOffset() : 0.25;
        double scale = userVideoConfig.getScale() != null ? userVideoConfig.getScale() : 1.0;

        VideoGenerateRequest build = VideoGenerateRequest.builder()
                .title(task.getTitle())
                .callbackId(task.getCallbackId())
                .callbackUrl(callbackUrl)
                .dimension(VideoGenerateRequest.Dimension.builder()
                        .width(userVideoConfig.getWidth())
                        .height(userVideoConfig.getHeight())
                        .build())
                .videoInputs(Collections.singletonList(
                        VideoGenerateRequest.VideoInput.builder()
                                .character(VideoGenerateRequest.Character.builder()
                                        .type("avatar")
                                        .avatarId(task.getAvatarId())
                                        .avatarStyle("normal")
                                        .offset(VideoGenerateRequest.Offset.builder()
                                                .x(xOffset)
                                                .y(yOffset)
                                                .build())
                                        .scale(scale)
                                        .build()
                                )
                                .voice(VideoGenerateRequest.Voice.builder()
                                        .type("text")
                                        .inputText(task.getDescription())
                                        .voiceId(task.getVoiceId())
                                        .build())
                                .background(background)
                                .build()
                ))
                .test(false)
                .caption(userVideoConfig.getIsCaption())
                .build();

        if (background.getType().equals("image") || background.getType().equals("color")) {
            build.setAspectRatio("16:9");
        }

        return build;
    }

    /**
     * 根据用户配置构建背景
     */
    private VideoGenerateRequest.Background buildBackground(UserVideoConfig userVideoConfig) {
        String backgroundType = userVideoConfig.getBackgroundType();
        if (backgroundType == null) {
            // 提供默认背景而不是返回null
            return VideoGenerateRequest.Background.builder()
                    .type("color")
                    .color("#ffffff") // 默认黑色背景
                    .build();
        }

        VideoGenerateRequest.Background.BackgroundBuilder builder = VideoGenerateRequest.Background.builder();

        switch (backgroundType) {
            case "color":
                builder.type("color")
                        .color(userVideoConfig.getBackgroundColor() != null ?
                                userVideoConfig.getBackgroundColor() : "#ffffff");
                break;
            case "image":
                builder.type("image");
                // 优先使用backgroundId
                if (userVideoConfig.getBackgroundId() != null && !userVideoConfig.getBackgroundId().isEmpty()) {
                    builder.imageAssetId(userVideoConfig.getBackgroundId());
                } else if (userVideoConfig.getBackgroundUrl() != null) {
                    builder.url(userVideoConfig.getBackgroundUrl());
                } else {
                    // 如果没有ID也没有URL，提供默认背景
                    return VideoGenerateRequest.Background.builder()
                            .type("color")
                            .color("#ffffff")
                            .build();
                }
                builder.fit(userVideoConfig.getBackgroundFit() != null ?
                        userVideoConfig.getBackgroundFit() : "cover");
                break;
            case "video":
                builder.type("video");
                // 优先使用backgroundId
                if (userVideoConfig.getBackgroundId() != null && !userVideoConfig.getBackgroundId().isEmpty()) {
                    builder.videoAssetId(userVideoConfig.getBackgroundId());
                } else if (userVideoConfig.getBackgroundUrl() != null) {
                    builder.url(userVideoConfig.getBackgroundUrl());
                } else {
                    builder.type("image");
                    // 如果没有ID也没有URL，提供默认背景
                    return VideoGenerateRequest.Background.builder()
                            .type("color")
                            .color("#ffffff")
                            .build();
                }
                builder.fit(userVideoConfig.getBackgroundFit() != null ?
                                userVideoConfig.getBackgroundFit() : "cover")
                        .playStyle(userVideoConfig.getBackgroundPlayStyle() != null ?
                                userVideoConfig.getBackgroundPlayStyle() : "loop");
                break;
            default:
                // 提供默认背景而不是返回null
                return VideoGenerateRequest.Background.builder()
                        .type("color")
                        .color("#ffffff") // 默认黑色背景
                        .build();
        }

        return builder.build();
    }
}